// repository/sql_logger.go
package repository

import (
	"context"
	"fmt"
	"gin-zc/util"
	"strings"
	"time"

	"go.uber.org/zap"
	"gorm.io/gorm/logger"
)

// SqlLogger 关联log_id的GORM日志器（写入sql.log）
type SqlLogger struct {
	ZapLogger     *zap.Logger     // 复用全局SQL日志实例
	SlowThreshold time.Duration   // 慢查询阈值
	LogLevel      logger.LogLevel // 日志级别
}

// NewSqlLogger 创建SQL日志器
func NewSqlLogger() *SqlLogger {
	return &SqlLogger{
		ZapLogger:     util.SqlLogger,         // 使用单独的SQL日志实例（写入sql.log）
		SlowThreshold: 500 * time.Millisecond, // 慢查询阈值：500ms
		LogLevel:      logger.Info,            // 开发环境：打印所有SQL
	}
}

// LogMode 设置日志级别
func (l *SqlLogger) LogMode(level logger.LogLevel) logger.Interface {
	newLogger := *l
	newLogger.LogLevel = level
	return &newLogger
}

// Info 信息级日志
func (l *SqlLogger) Info(ctx context.Context, msg string, data ...interface{}) {
	if l.LogLevel < logger.Info {
		return
	}
	logID := getLogIDFromCtx(ctx)
	l.ZapLogger.Info(
		msg,
		zap.String("log_id", logID),
		zap.String("details", formatMessage(msg, data...)),
	)
}

// Warn 警告级日志（如慢查询）
func (l *SqlLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
	if l.LogLevel < logger.Warn {
		return
	}
	logID := getLogIDFromCtx(ctx)
	l.ZapLogger.Warn(
		msg,
		zap.String("log_id", logID),
		zap.String("details", formatMessage(msg, data...)),
	)
}

// Error 错误级日志（如SQL执行失败）
func (l *SqlLogger) Error(ctx context.Context, msg string, data ...interface{}) {
	if l.LogLevel < logger.Error {
		return
	}
	logID := getLogIDFromCtx(ctx)
	l.ZapLogger.Error(
		msg,
		zap.String("log_id", logID),
		zap.String("details", formatMessage(msg, data...)),
	)
}

// Trace 记录SQL执行详情（核心：关联log_id）
func (l *SqlLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
	if l.LogLevel <= 0 {
		return
	}

	elapsed := time.Since(begin)
	sql, rows := fc()
	sql = cleanSQL(sql) // 过滤特殊字符
	logID := getLogIDFromCtx(ctx)

	// 日志字段
	fields := []zap.Field{
		zap.String("log_id", logID),
		zap.String("sql", sql),
		zap.Int64("rows_affected", rows),
		zap.Duration("cost_ms", elapsed),
	}

	// 错误处理
	if err != nil {
		l.ZapLogger.Error("sql_error", append(fields, zap.Error(err))...)
		return
	}

	// 慢查询警告
	if elapsed > l.SlowThreshold {
		l.ZapLogger.Warn("slow_sql", fields...)
		return
	}

	// 正常SQL日志
	l.ZapLogger.Info("sql_success", fields...)
}

// 从context提取log_id
func getLogIDFromCtx(ctx context.Context) string {
	logID, ok := ctx.Value("log_id").(string)
	if !ok {
		// 调试：打印未获取到log_id的原因
		//fmt.Println("SQL日志器未从context中获取到log_id")
		return "unknown"
	}
	return logID
}

// 自定义FormatMessage，替代gorm/utils的FormatMessage
func formatMessage(format string, v ...interface{}) string {
	if len(v) == 0 {
		return format
	}
	return fmt.Sprintf(format, v...)
}

// 过滤SQL中的NUL字符和不可见字符
func cleanSQL(sql string) string {
	// 替换NUL字符（\x00）为空格
	cleaned := strings.ReplaceAll(sql, "\x00", " ")
	// 可选：过滤其他不可见字符（如控制字符）
	return cleaned
}
